/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { BaseElement, element } from '../BaseElement';

const initHtmlStyle: string = `
    <style>
        :host{ 
            display:inline-block; 
            -webkit-tap-highlight-color: transparent;
        }
        #name{
            transition:0.31s width,0.31s height,0.31s background-color;
            width:2.41em;
            height:1.21em;
            background: #3391FF;
            display:flex;
            padding:0.124em;
            border-radius:1.21em;
            cursor:pointer;
        }
        
        :host(:not([checked])) #name {
           background: #999999;
        }
       
        #name::before{
            content:'';
            flex:0;
            transition:.2s cubic-bezier(.12, .4, .29, 1.46) flex;
        }
        #name::after{
            content:'';
            width:.4em;
            height:.4em;
            border-radius:1.2em;
            border:.4em solid #fff;
            background-color:#ffffff;
            transition:.3s background,.3s padding,.3s width,.3s height,.3s border-radius,.3s border;
            box-shadow: 0 2px 4px 0 rgba(0,35,11,0.2);
        }
        #name:active::after{
            padding:0 .3em;
        }
        #switch:checked+#name{
            background:#42b983);
        }
        #switch:checked+#name::before{
            flex:1;
        }
        #switch{
            position:absolute;
            clip:rect(0,0px,0px,0);
        }
        :host(:focus-within) #name::after,:host(:active) ::after{ 
            background:#42b983;
        }
        :host(:focus-within) #name{ 
            box-shadow: 0 0 10px rgba(0,0,0,0.1); 
        }
        :host(:focus-within) #switch,:host(:active) #switch{
            z-index:2
        }
        :host([disabled]){ 
            pointer-events: none; 
            opacity:.5; 
        }
        :host([disabled]) #name{ 
            pointer-events: all;  
            cursor: not-allowed; 
        }
        </style>
    `;

@element('lit-switch')
export default class LitSwitch extends BaseElement {
  private switch: HTMLInputElement | null | undefined;
  private isfocus: boolean | undefined;

  static get observedAttributes(): string[] {
    return ['disabled', 'checked'];
  }

  get disabled(): boolean {
    return this.getAttribute('disabled') !== null;
  }

  get checked(): boolean {
    return this.getAttribute('checked') !== null;
  }

  set checked(value) {
    if (value === null || value === false) {
      this.removeAttribute('checked');
    } else {
      this.setAttribute('checked', '');
    }
  }

  set disabled(value: boolean) {
    if (value === null || value === false) {
      this.removeAttribute('disabled');
    } else {
      this.setAttribute('disabled', '');
    }
  }

  get name(): string | null {
    return this.getAttribute('name');
  }

  initElements(): void {}

  initHtml(): string {
    return `
        ${initHtmlStyle}
        <input type="checkbox" id="switch"><label id="name" for="switch"></label>
        `;
  }

  connectedCallback(): void {
    this.switch = this.shadowRoot?.getElementById('switch') as HTMLInputElement;
    this.disabled = this.disabled;
    this.checked = this.checked;
    this.switch!.onchange = (ev): void => {
      this.checked = this.switch!.checked;
      let changeEvent: CustomEventInit<LitSwitchChangeEvent> = {
        detail: {
          checked: this.checked,
        },
      };
      this.dispatchEvent(new CustomEvent('change', changeEvent));
    };
    this.switch.onkeydown = (ev): void => {
      switch (ev.keyCode) {
        case 13: //enter
          this.checked = !this.checked;
          let changeEvent: CustomEventInit<LitSwitchChangeEvent> = {
            detail: {
              checked: this.checked,
            },
          };
          this.dispatchEvent(new CustomEvent('change', changeEvent));
          break;
        default:
          break;
      }
    };
    this.setEvent();
  }

  setEvent(): void {
    this.switch!.onfocus = (ev): void => {
      ev.stopPropagation();
      if (!this.isfocus) {
        this.dispatchEvent(
          new CustomEvent('focus', {
            detail: { value: this.switch!.value },
          })
        );
      }
    };
    this.switch!.onblur = (ev): void => {
      ev.stopPropagation();
      if (getComputedStyle(this.switch!).zIndex === '2') {
        this.isfocus = true;
      } else {
        this.isfocus = false;
        this.dispatchEvent(
          new CustomEvent('blur', {
            detail: { value: this.switch!.value },
          })
        );
      }
    };
  }

  attributeChangedCallback(name: string, oldValue: string, newValue: string): void {
    if (name === 'disabled' && this.switch) {
      if (newValue !== null) {
        this.switch.setAttribute('disabled', '');
      } else {
        this.switch.removeAttribute('disabled');
      }
    }
    if (name === 'checked' && this.switch) {
      if (newValue !== null) {
        this.switch.checked = true;
      } else {
        this.switch.checked = false;
      }
    }
  }
}

export interface LitSwitchChangeEvent {
  checked: boolean;
}
